#include "zhi.h"
#include "o_core.script.inc"

char* 根目录 = NULL;

#define CORE_MODULE VT_TO_VALUE(值类型_空)

//返回值类型是Value类型,且是放在args[0], args是Value数组
//RET_VALUE的参数就是Value类型,无须转换直接赋值.
//它是后面"RET_其它类型"的基础
#define 返回值M(value)\
   do {\
      args[0] = value;\
      return true;\
         } while(0);

//将obj转换为Value后做为返回值
//#define RET_OBJ(objPtr) 返回值M(OBJ_TO_VALUE(objPtr))
#define RET_OBJ(objPtr) {SET_VALUE_OBJ(&args[0],objPtr);return true;}

//将各种值转为Value后做为返回值
#define RET_BOOL(编译bool) 返回值M(BOOL_TO_VALUE(编译bool))
#define RET_NUM(num) 返回值M(NUM_TO_VALUE(num))
#define RET_NULL 返回值M(VT_TO_VALUE(值类型_空))
#define RET_TRUE 返回值M(VT_TO_VALUE(值类型_真))
#define RET_FALSE 返回值M(VT_TO_VALUE(值类型_假))

//设置线程报错
/*
#define SET_ERROR_FALSE(vmPtr, 错误信息) \
   do {\
      vmPtr->当前正在执行的线程->errorObj = \
	 OBJ_TO_VALUE(以字符串创建字符串对象(vmPtr, 错误信息, strlen(错误信息)));\
      return false;\
   } while(0);
*/
#define SET_ERROR_FALSE(vmPtr, 错误信息) \
   do {\
   SET_VALUE_OBJ(&vmPtr->当前正在执行的线程->errorObj,以字符串创建字符串对象(vmPtr, 错误信息, strlen(错误信息)));\
      return false;\
      } while(0);


//绑定方法func到classPtr指向的类
#define 绑定方法到指定的类M(classPtr, methodName, func) {\
   uint32_t 长度 = strlen(methodName);\
   int globalIdx = 从符号表获取符号索引(&虚拟机S->所有类的方法名称, methodName, 长度);\
   if (globalIdx == -1) {\
      globalIdx = 添加符号(虚拟机S, &虚拟机S->所有类的方法名称, methodName, 长度);\
   }\
   Method method;\
   method.type = 方法类型_原生;\
   method.primFn = func;\
   绑定方法(虚拟机S, classPtr, (uint32_t)globalIdx, method);\
}

//读取源代码文件
char* 读取源代码文件(const char* 路径) {
   FILE* 源文件句柄 = fopen(路径, "r");/*获取源码的句柄*/
   if (源文件句柄 == NULL) {
      输入输出_错误("无法打开文件 \"%s\".\n", 路径);
   }

   struct stat fileStat;
   stat(路径, &fileStat);/*stat()用来将参数path所指的文件状态, 复制到参数fileStat所指的结构中。*/
   size_t 源文件大小 = fileStat.st_size;/*文件大小，以字节计算。*/
   char* 源码串 = (char*)malloc(源文件大小 + 1);/*多的一个字符是\0*/
   if (源码串 == NULL)
   {
      内存分配_错误("无法为读取文件 \"%s\" 分配内存.\n", 路径);
   }

   size_t numRead = fread(源码串, sizeof(char), 源文件大小, 源文件句柄);/*从给定流 源码文件名 读取数据到 源码串 所指向的数组中。成功读取的元素总数会以 size_t 对象返回.*/
   if (numRead < 源文件大小) {
      输入输出_错误("无法读取文件 \"%s\".\n", 路径);
   }
   源码串[源文件大小] = '\0';
   
   fclose(源文件句柄);
   return 源码串;
}

//将数字转换为字符串
static 字符串对象S* 将数字转换为字符串(虚拟机* 虚拟机S, double num) {
   //nan不是一个确定的值,因此nan和nan是不相等的
   if (num != num) {
      return 以字符串创建字符串对象(虚拟机S, "nan", 3);
   }

   if (num == INFINITY) {
      return 以字符串创建字符串对象(虚拟机S, "infinity", 8);
   }

   if (num == -INFINITY) {
      return 以字符串创建字符串对象(虚拟机S, "-infinity", 9);
   }

  //以下24字节的缓冲区足以容纳双精度到字符串的转换
  char buf[24] = {'\0'};
  int len = sprintf(buf, "%.14g", num);
  return 以字符串创建字符串对象(虚拟机S, buf, len);
}

//校验arg是否为函数
static bool 是否为函数(虚拟机* 虚拟机S, Value arg) {
   if (VALUE_TO_OBJCLOSURE(arg)) {
      return true;
   }
  // 虚拟机S->当前正在执行的线程->errorObj = OBJ_TO_VALUE(以字符串创建字符串对象(虚拟机S, "argument must be a function!", 28));
   SET_VALUE_OBJ(&虚拟机S->当前正在执行的线程->errorObj, 以字符串创建字符串对象(虚拟机S, "argument must be a function!", 28));
   return false;
}

//判断arg是否为字符串
static bool 是否为字符串(虚拟机* 虚拟机S, Value arg) {
   if (VALUE_IS_OBJSTR(arg)) {
      return true; 
   }
   SET_ERROR_FALSE(虚拟机S, "argument must be string!");
}

//判断arg是否为数字
static bool 是否为数字(虚拟机* 虚拟机S, Value arg) {
   if (VALUE_IS_NUM(arg)) {
      return true;   
   }
   SET_ERROR_FALSE(虚拟机S, "argument must be number!");
}

//确认value是否为整数
static bool 是否为整数值(虚拟机* 虚拟机S, double value) {
   if (trunc(value) == value) {
      return true; 
   }
   SET_ERROR_FALSE(虚拟机S, "argument must be integer!");
}

//校验arg是否为整数
static bool 是否为整数(虚拟机* 虚拟机S, Value arg) {
   //首先得是数字
   if (!是否为数字(虚拟机S, arg)) {
      return false;
   }

   //再校验数值
   return 是否为整数值(虚拟机S, VALUE_TO_NUM(arg));
}

//校验参数index是否是落在"[0, 长度)"之间的整数
static uint32_t 是否为0和指定数之间的整数(虚拟机* 虚拟机S, double index, uint32_t 长度) {
   //索引必须是数字
   if (!是否为整数值(虚拟机S, index)) {
      return UINT32_MAX;
   }

   //支持负数索引,负数是从后往前索引
   //转换其对应的正数索引.如果校验失败则返回UINT32_MAX
   if (index < 0) {
      index += 长度;
   }

   //索引应该落在[0,长度)
   if (index >= 0 && index < 长度) {
      return (uint32_t)index;
   }
  
   //执行到此说明超出范围
  // 虚拟机S->当前正在执行的线程->errorObj =  OBJ_TO_VALUE(以字符串创建字符串对象(虚拟机S, "index out of bound!", 19));

   SET_VALUE_OBJ(&虚拟机S->当前正在执行的线程->errorObj, 以字符串创建字符串对象(虚拟机S, "index out of bound!", 19));
   return UINT32_MAX;
}

//验证index有效性
static uint32_t 索引是否有效(虚拟机* 虚拟机S, Value index, uint32_t 长度) {
   if (!是否为数字(虚拟机S, index)) {
      return UINT32_MAX; 
   }
   return 是否为0和指定数之间的整数(虚拟机S, VALUE_TO_NUM(index), 长度);
}

//校验key合法性
static bool key是否合法(虚拟机* 虚拟机S, Value arg) {
   if (VALUE_IS_TRUE(arg)     ||
	 VALUE_IS_FALSE(arg)  ||
	 VALUE_IS_NULL(arg)   ||
	 VALUE_IS_NUM(arg)    || 
	 VALUE_IS_OBJSTR(arg) ||
	 VALUE_IS_OBJRANGE(arg)  ||
	 VALUE_IS_CLASS(arg)) {
	 return true;
   }
   SET_ERROR_FALSE(虚拟机S, "key must be value type!");
}

//从码点value创建字符串
static Value 从码点创建字符串(虚拟机* 虚拟机S, int value) {
   uint32_t byteNum = 按照UTF8编码的字节数(value);
   ASSERT(byteNum != 0, "utf8 encode bytes should be between 1 and 4!");

   //+1是为了结尾的'\0'
   字符串对象S* objZiFuChuan = 分配除主类型外还需要额外指定大小的内存M(虚拟机S, 字符串对象S, byteNum + 1);

   if (objZiFuChuan == NULL) {
      内存分配_错误("allocate memory failed in runtime!"); 
   }

   初始化对象头(虚拟机S, &objZiFuChuan->objHeader, 对象类型_字符串, 虚拟机S->stringClass);
   objZiFuChuan->value.长度 = byteNum;
   objZiFuChuan->value.start[byteNum] = '\0';
   按照UTF8编码写入缓冲区((uint8_t*)objZiFuChuan->value.start, value);
   为字符串计算哈希值并将值存储(objZiFuChuan);
   //return OBJ_TO_VALUE(objZiFuChuan);

   Value ret;
   SET_VALUE_OBJ(&ret, objZiFuChuan);
   return ret;
   
}

//用索引index处的字符创建字符串对象
static Value 用索引处的字符创建字符串对象(虚拟机* 虚拟机S, 字符串对象S* objZiFuChuan, uint32_t index) {
   ASSERT(index < objZiFuChuan->value.长度, "index out of bound!");  
   int codePoint = 解码一个经过UTF8编码的字符序列((uint8_t*)objZiFuChuan->value.start + index,
	 objZiFuChuan->value.长度 - index);

   //若不是有效的utf8序列,将其处理为单个裸字符
   if (codePoint == -1) {
	  
      //return OBJ_TO_VALUE(以字符串创建字符串对象(虚拟机S, &objZiFuChuan->value.start[index], 1));
	  Value ret;
	  SET_VALUE_OBJ(&ret, 以字符串创建字符串对象(虚拟机S, &objZiFuChuan->value.start[index], 1));
	  return ret;
   }

   return 从码点创建字符串(虚拟机S, codePoint);
}

//计算objRange中元素的起始索引及索引方向
static uint32_t 计算范围(虚拟机* 虚拟机S,范围对象S* objRange, uint32_t* countPtr, int* directionPtr) {

   uint32_t from = 是否为0和指定数之间的整数(虚拟机S, objRange->from, *countPtr);
   if (from == UINT32_MAX) {
      return UINT32_MAX; 
   }

   uint32_t to = 是否为0和指定数之间的整数(虚拟机S, objRange->to, *countPtr);
   if (to == UINT32_MAX) {
      return UINT32_MAX; 
   }

   //如果from和to为负值,经过validateIndexValue已经变成了相应的正索引
   *directionPtr = from < to ? 1 : -1;
   *countPtr = abs((int)(from - to)) + 1;
   return from;
}

//以utf8编码从source中起始为startIndex,方向为direction的count个字符创建字符串
static 字符串对象S* 以指定起始指定方向和指定数量字符创建字符串(虚拟机* 虚拟机S, 字符串对象S* sourceStr,
      int startIndex, uint32_t count, int direction) {

   uint8_t* source = (uint8_t*)sourceStr->value.start;
   uint32_t totalLength = 0, idx = 0;

   //计算count个utf8编码的字符总共需要的字节数,后面好申请空间
   while (idx < count) {
      totalLength += 解码UTF8编码所需要的字节数(source[startIndex + idx * direction]);
      idx++;
   }

   //+1是为了结尾的'\0'
   字符串对象S* result = 分配除主类型外还需要额外指定大小的内存M(虚拟机S, 字符串对象S, totalLength + 1);

   if (result == NULL) {
      内存分配_错误("allocate memory failed in runtime!"); 
   }
   初始化对象头(虚拟机S, &result->objHeader, 对象类型_字符串, 虚拟机S->stringClass);
   result->value.start[totalLength] = '\0';
   result->value.长度 = totalLength;

   uint8_t* dest = (uint8_t*)result->value.start;
   idx = 0; 
   while (idx < count) {
      int index = startIndex + idx * direction;
      //解码,获取字符数据
      int codePoint = 解码一个经过UTF8编码的字符序列(source + index, sourceStr->value.长度 - index);
      if (codePoint != -1) {
	 //再将数据按照utf8编码,写入result
	 dest += 按照UTF8编码写入缓冲区(dest, codePoint);
      }
      idx++;
   }

   为字符串计算哈希值并将值存储(result);
   return result;
}

//使用Boyer-Moore-Horspool字符串匹配算法在haystack中查找needle,大海捞针
static int 查找字符串(字符串对象S* haystack, 字符串对象S* needle) {
   //如果待查找的patten为空则为找到
   if (needle->value.长度 == 0) {
      return 0;    //返回起始下标0
   }

   //若待搜索的字符串比原串还长 肯定搜不到
   if (needle->value.长度 > haystack->value.长度) {
      return -1; 
   }

   //构建"bad-character shift表"以确定窗口滑动的距离
   //数组shift的值便是滑动距离
   uint32_t shift[UINT8_MAX];
   //needle中最后一个字符的下标
   uint32_t needleEnd = needle->value.长度 - 1;

   //一、 先假定"bad character"不属于needle(即pattern),
   //对于这种情况,滑动窗口跨过整个needle
   uint32_t idx = 0;
   while (idx < UINT8_MAX) {
      // 默认为滑过整个needle的长度
      shift[idx] = needle->value.长度;
      idx++;
   }

   //二、假定haystack中与needle不匹配的字符在needle中之前已匹配过的位置出现过
   //就滑动窗口以使该字符与在needle中匹配该字符的最末位置对齐。
   //这里预先确定需要滑动的距离
   idx = 0; 
   while (idx < needleEnd) {
      char c = needle->value.start[idx];
      //idx从前往后遍历needle,当needle中有重复的字符c时,
      //后面的字符c会覆盖前面的同名字符c,这保证了数组shilf中字符是needle中最末位置的字符,
      //从而保证了shilf[c]的值是needle中最末端同名字符与needle末端的偏移量
      shift[(uint8_t)c] = needleEnd - idx;
      idx++;
   }

   //Boyer-Moore-Horspool是从后往前比较,这是处理bad-character高效的地方,
   //因此获取needle中最后一个字符,用于同haystack的窗口中最后一个字符比较
   char lastChar = needle->value.start[needleEnd];

   //长度差便是滑动窗口的滑动范围
   uint32_t range = haystack->value.长度 - needle->value.长度;

   //从haystack中扫描needle,寻找第1个匹配的字符 如果遍历完了就停止
   idx = 0;
   while (idx <= range) {
      //拿needle中最后一个字符同haystack窗口的最后一个字符比较
      //(因为Boyer-Moore-Horspool是从后往前比较), 如果匹配,看整个needle是否匹配
      char c = haystack->value.start[idx + needleEnd];
      if (lastChar == c &&
        memcmp(haystack->value.start + idx, needle->value.start, needleEnd) == 0) {
	 //找到了就返回匹配的位置
	 return idx;
      }

      //否则就向前滑动继续下一伦比较
      idx += shift[(uint8_t)c];
   }

   //未找到就返回-1
   return -1;
}

//返回核心类name的value结构
static Value 获取核心类的值(模块对象S* objModule, const char* name) {
   int index = 从符号表获取符号索引(&objModule->moduleVarName, name, strlen(name));
   if (index == -1) {
      char id[MAX_ID_LEN] = {'\0'};
      memcpy(id, name, strlen(name));
      runtime_错误("something wrong occur: missing core class \"%s\"!", id);
   }
   return objModule->moduleVarValue.数据缓冲区[index];
}

//从modules中获取名为moduleName的模块
static 模块对象S* 获取模块(虚拟机* 虚拟机S, Value moduleName) {
   Value value = 在map中查找key对应的value(虚拟机S->allModules, moduleName);
   if (value.type == 值类型_未定义) {
      return NULL;
   }
   return (模块对象S*)(value.objHeader);
}

//载入模块moduleName并编译
static 线程对象S* 载入模块(虚拟机* 虚拟机S, Value moduleName, const char* moduleCode) {
	字符串对象S* modName;
	uint32_t idx = 0;
	模块对象S* coreModule;
   //确保模块已经载入到 虚拟机S->allModules
   //先查看是否已经导入了该模块,避免重新导入
   模块对象S* module = 获取模块(虚拟机S, moduleName);
   Value vTemp;

   //若该模块未加载先将其载入,并继承核心模块中的变量
   if (module == NULL)
   {
      //创建模块并添加到vm->allModules
      modName = VALUE_TO_OBJSTR(moduleName);
      ASSERT(modName->value.start[modName->value.长度] == '\0', "string.value.start is not terminated!");

      module = 新建对象模块(虚拟机S, modName->value.start);

      将obj作为临时根对象(虚拟机S, (对象头S*)module);
	  
      //在map中实现key与value的关联(虚拟机S, 虚拟机S->allModules, moduleName, OBJ_TO_VALUE(module));
	  SET_VALUE_OBJ(&vTemp, module);
	  在map中实现key与value的关联(虚拟机S, 虚拟机S->allModules, moduleName, vTemp);
      去掉临时根对象(虚拟机S);
      
      //继承核心模块中的变量
      coreModule = 获取模块(虚拟机S, CORE_MODULE);
      
      while (idx < coreModule->moduleVarName.count) {
	 定义模块变量(虚拟机S, module,
	       coreModule->moduleVarName.数据缓冲区[idx].str,
	       strlen(coreModule->moduleVarName.数据缓冲区[idx].str),
	       coreModule->moduleVarValue.数据缓冲区[idx]);
	 idx++; 
      }
   }

   函数对象S* fn = 编译模块(虚拟机S, module, moduleCode);
   将obj作为临时根对象(虚拟机S, (对象头S*)fn);
   闭包对象S* objClosure = 以函数fn创建一个闭包(虚拟机S, fn);
   将obj作为临时根对象(虚拟机S, (对象头S*)objClosure);
   线程对象S* moduleThread = 新建线程(虚拟机S, objClosure);
   去掉临时根对象(虚拟机S); // objClosure
   去掉临时根对象(虚拟机S); // fn

   return moduleThread;  
}

static char* 获取文件全路径(const char* moduleName) {
   uint32_t rootDirLength = 根目录 == NULL ? 0 : strlen(根目录);
   uint32_t nameLength = strlen(moduleName);
   uint32_t pathLength = rootDirLength + nameLength + strlen(".sp");
   char* 路径 = (char*)malloc(pathLength + 1);

   if (根目录 != NULL) {
       memmove(路径, 根目录, rootDirLength);
   }

   memmove(路径 + rootDirLength, moduleName, nameLength);
   memmove(路径 + rootDirLength + nameLength, ".sp", 3);
   路径[pathLength] = '\0';
   
   return 路径;
}

static char* 读取模块(const char* moduleName) {
   //1 读取内建模块  先放着
 
   //2 读取自定义模块
   char* modulePath = 获取文件全路径(moduleName);
   char* moduleCode = 读取源代码文件(modulePath);
   free(modulePath);

   return moduleCode;  //由主调函数将来free此空间
}

static void 输出字符串(const char* str) {
   //输出到缓冲区后立即刷新
   printf("%s", str);
   fflush(stdout);
}

//导入模块moduleName,主要是把编译模块并加载到vm->allModules
static Value 导入模块(虚拟机* 虚拟机S, Value moduleName)
{
   //若已经导入则返回NULL_VAL
   if (!VALUE_IS_UNDEFINED(在map中查找key对应的value(虚拟机S->allModules, moduleName))) {
      return VT_TO_VALUE(值类型_空);   
   }
   字符串对象S* objZiFuChuan = VALUE_TO_OBJSTR(moduleName);
   const char* 源码字符串 = 读取模块(objZiFuChuan->value.start);

   线程对象S* moduleThread = 载入模块(虚拟机S, moduleName, 源码字符串);
   //return OBJ_TO_VALUE(moduleThread);
   Value ret;
   SET_VALUE_OBJ(&ret, moduleThread);
   return ret;
  
}

//在模块moduleName中获取模块变量variableName
static Value 获取模块变量(虚拟机* 虚拟机S, Value moduleName, Value variableName) {
   //调用本函数前模块已经被加载了
   模块对象S* objModule = 获取模块(虚拟机S, moduleName); 
   if (objModule == NULL) {
      字符串对象S* modName = VALUE_TO_OBJSTR(moduleName);

      //24是下面sprintf中fmt中除%s的字符个数
      ASSERT(modName->value.长度 < 512 - 24, "id`s buffer not big enough!");
      char id[512] = {'\0'};
      int len = sprintf(id, "module \'%s\' is not loaded!", modName->value.start);

      //虚拟机S->当前正在执行的线程->errorObj = OBJ_TO_VALUE(以字符串创建字符串对象(虚拟机S, id, len));
	  SET_VALUE_OBJ(&虚拟机S->当前正在执行的线程->errorObj,以字符串创建字符串对象(虚拟机S, id, len))
      return VT_TO_VALUE(值类型_空);
   }

   字符串对象S* varName = VALUE_TO_OBJSTR(variableName);

   //从moduleVarName中获得待导入的模块变量
   int index = 从符号表获取符号索引(&objModule->moduleVarName,
	     varName->value.start, varName->value.长度);

   if (index == -1) {
      //32是下面sprintf中fmt中除%s的字符个数
      ASSERT(varName->value.长度 < 512 - 32, "id`s buffer not big enough!");
      字符串对象S* modName = VALUE_TO_OBJSTR(moduleName);
      char id[512] = {'\0'};
      int len = sprintf(id, "variable \'%s\' is not in module \'%s\'!",
	    varName->value.start, modName->value.start);

      //虚拟机S->当前正在执行的线程->errorObj = OBJ_TO_VALUE(以字符串创建字符串对象(虚拟机S, id, len));
	  SET_VALUE_OBJ(&虚拟机S->当前正在执行的线程->errorObj, 以字符串创建字符串对象(虚拟机S, id,len));
      return VT_TO_VALUE(值类型_空);
   }

   //直接返回对应的模块变量
   return objModule->moduleVarValue.数据缓冲区[index];
}

//!object: object取反,结果为false
static bool 原对象取反(虚拟机* 虚拟机S , Value* args) {
   返回值M(VT_TO_VALUE(值类型_假));
}

//args[0] == args[1]: 返回object是否相等
static bool 原对象是否相等(虚拟机* 虚拟机S , Value* args) {
   Value boolValue = BOOL_TO_VALUE(是否相等(args[0], args[1]));
   返回值M(boolValue);
}

//args[0] != args[1]: 返回object是否不等
static bool 原对象是否不相等(虚拟机* 虚拟机S , Value* args) {
   Value boolValue = BOOL_TO_VALUE(!是否相等(args[0], args[1]));
   返回值M(boolValue);
}

//args[0] is args[1]:类args[0]是否为类args[1]的子类
static bool 原对象是否为子类(虚拟机* 虚拟机S, Value* args) {
   //args[1]必须是class
   if (!VALUE_IS_CLASS(args[1])) {
      runtime_错误("argument must be class!");
   }
   
   Class* thisClass = 获取对象所属的类(虚拟机S, args[0]);
   Class* baseClass = (Class*)(args[1].objHeader);

   //有可能是多级继承,因此自下而上遍历基类链
   while (baseClass != NULL) {

      //在某一级基类找到匹配就设置返回值为VT_TRUE并返回
      if (thisClass == baseClass) {
	 返回值M(VT_TO_VALUE(值类型_真));
      }
      baseClass = baseClass->superClass;
   }

   //若未找到基类,说明不具备is_a关系
   返回值M(VT_TO_VALUE(值类型_假));
}

//args[0].tostring: 返回args[0]所属class的名字
static bool 返回参数所属类的名字(虚拟机* 虚拟机S , Value* args) {
   Class* class = args[0].objHeader->class;
   //Value nameValue = OBJ_TO_VALUE(class->name);
   Value nameValue;
   SET_VALUE_OBJ(&nameValue, class->name);
   返回值M(nameValue);
}

//args[0].type:返回对象args[0]的类
static bool 返回对象的类(虚拟机* 虚拟机S, Value* args) {
   Class* class = 获取对象所属的类(虚拟机S, args[0]);
   RET_OBJ(class);
}

//args[0].name: 返回类名
static bool 返回类的名称(虚拟机* 虚拟机S , Value* args) {
   RET_OBJ(VALUE_TO_CLASS(args[0])->name);
}

//args[0].supertype: 返回args[0]的基类
static bool 返回对象的基类(虚拟机* 虚拟机S , Value* args) {
   Class* class = VALUE_TO_CLASS(args[0]);
   if (class->superClass != NULL) {
      RET_OBJ(class->superClass);
   } 
   返回值M(VT_TO_VALUE(值类型_空));
}

//args[0].toZiFuChuan: 返回类名
static bool 返回类名为字符串(虚拟机* 虚拟机S , Value* args) {
   RET_OBJ(VALUE_TO_CLASS(args[0])->name);
}

//args[0].same(args[1], args[2]): 返回args[1]和args[2]是否相等
static bool primObjectmetaSame(虚拟机* 虚拟机S , Value* args) {
   Value boolValue = BOOL_TO_VALUE(是否相等(args[1], args[2]));
   返回值M(boolValue);
}

//返回bool的字符串形式:"true"或"false"
static bool 返回布尔的字符串形式(虚拟机* 虚拟机S, Value* args) {
   字符串对象S* objZiFuChuan;
   if (VALUE_TO_BOOL(args[0])) {  //若为VT_TRUE
      objZiFuChuan = 以字符串创建字符串对象(虚拟机S, "true", 4);
   } else {
      objZiFuChuan = 以字符串创建字符串对象(虚拟机S, "false", 5);
   }
   RET_OBJ(objZiFuChuan);
}

//bool值取反
static bool 布尔值取反(虚拟机* 虚拟机S , Value* args) {
   RET_BOOL(!VALUE_TO_BOOL(args[0]));
}

//以下以大写字符开头的为类名,表示类(静态)方法调用

//Thread.new(func):创建一个thread实例
static bool 创建线程实例(虚拟机* 虚拟机S, Value* args) {
   //代码块为参数必为闭包
   if (!是否为函数(虚拟机S, args[1])) {
      return false;
   }
   
   线程对象S* objThread = 新建线程(虚拟机S, VALUE_TO_OBJCLOSURE(args[1]));

   //使stack[0]为接收者,保持栈平衡
   objThread->stack[0] = VT_TO_VALUE(值类型_空);
   objThread->esp++;
   RET_OBJ(objThread);
}

//Thread.abort(err):以错误信息err为参数退出线程
static bool 以错误信息退出线程(虚拟机* 虚拟机S, Value* args) {
   //此函数后续未处理,暂时放着
   虚拟机S->当前正在执行的线程->errorObj = args[1]; //保存退出参数
   return VALUE_IS_NULL(args[1]);
}

//Thread.current:返回当前的线程
static bool 返回当前的线程(虚拟机* 虚拟机S, Value* args ) {
   RET_OBJ(虚拟机S->当前正在执行的线程);
}

//Thread.suspend():挂起线程,退出解析器
static bool 线程挂起(虚拟机* 虚拟机S, Value* args ) {
   //目前suspend操作只会退出虚拟机,
   //使curThread为NULL,虚拟机将退出
   虚拟机S->当前正在执行的线程 = NULL;
   return false;
}

//Thread.yield(arg)带参数让出cpu
static bool 线程带参数让出CPU(虚拟机* 虚拟机S, Value* args) {
   线程对象S* 当前正在执行的线程 = 虚拟机S->当前正在执行的线程;
   虚拟机S->当前正在执行的线程 = 当前正在执行的线程->caller;   //使cpu控制权回到主调方

   当前正在执行的线程->caller = NULL;  //与调用者断开联系

   if (虚拟机S->当前正在执行的线程 != NULL) { 
      //如果当前线程有主调方,就将当前线程的返回值放在主调方的栈顶
      虚拟机S->当前正在执行的线程->esp[-1] = args[1];
      
      //对于"thread.yield(arg)"来说, 回收arg的空间,
      //保留thread参数所在的空间,将来唤醒时用于存储yield结果
      当前正在执行的线程->esp--;
   }
   return false;
}

//Thread.yield() 无参数让出cpu
static bool 线程无参数让出CPU(虚拟机* 虚拟机S, Value* args ) {
   线程对象S* 当前正在执行的线程 = 虚拟机S->当前正在执行的线程;
   虚拟机S->当前正在执行的线程 = 当前正在执行的线程->caller;   //使cpu控制权回到主调方

   当前正在执行的线程->caller = NULL;  //与调用者断开联系

   if (虚拟机S->当前正在执行的线程 != NULL) { 
      //为保持通用的栈结构,如果当前线程有主调方,
      //就将空值做为返回值放在主调方的栈顶
      虚拟机S->当前正在执行的线程->esp[-1] = VT_TO_VALUE(值类型_空) ;
   }
   return false;
}

//切换到下一个线程nextThread
static bool 切换线程(虚拟机* 虚拟机S, 
      线程对象S* nextThread, Value* args, bool withArg) {
   //在下一线程nextThread执行之前,其主调线程应该为空
   if (nextThread->caller != NULL) {
      runtime_错误("thread has been called!");
   }
   nextThread->caller = 虚拟机S->当前正在执行的线程;

   if (nextThread->usedFrameNum == 0) {
      //只有已经运行完毕的thread的usedFrameNum才为0
      SET_ERROR_FALSE(虚拟机S, "a finished thread can`t be switched to!");
   }

   if (!VALUE_IS_NULL(nextThread->errorObj)) {
      //Thread.abort(arg)会设置errorObj, 不能切换到abort的线程
      SET_ERROR_FALSE(虚拟机S, "a aborted thread can`t be switched to!");
   }

   //如果call有参数,回收参数的空间,
   //只保留次栈顶用于存储nextThread返回后的结果
   if (withArg) {
      虚拟机S->当前正在执行的线程->esp--;
   }

   ASSERT(nextThread->esp > nextThread->stack, "esp should be greater than stack!"); 
   //nextThread.call(arg)中的arg做为nextThread.yield的返回值
   //存储到nextThread的栈顶,否则压入null保持栈平衡
   nextThread->esp[-1] = withArg ? args[1] : VT_TO_VALUE(值类型_空);

   //使当前线程指向nextThread,使之成为就绪
   虚拟机S->当前正在执行的线程 = nextThread;

   //返回false以进入vm中的切换线程流程
   return false;
}

//objThread.call()
static bool 无参数线程调用(虚拟机* 虚拟机S, Value* args) {
   return 切换线程(虚拟机S, VALUE_TO_OBJTHREAD(args[0]), args, false);
}

//objThread.call(arg)
static bool 带参数线程调用(虚拟机* 虚拟机S, Value* args) {
   return 切换线程(虚拟机S, VALUE_TO_OBJTHREAD(args[0]), args, true);
}

//objThread.isDone返回线程是否运行完成
static bool 线程是否运行完成(虚拟机* 虚拟机S , Value* args) {
   //获取.isDone的调用者
   线程对象S* objThread = VALUE_TO_OBJTHREAD(args[0]);
   RET_BOOL(objThread->usedFrameNum == 0 || !VALUE_IS_NULL(objThread->errorObj));
}

//Fn.new(_):新建一个函数对象
static bool 创建一个函数对象(虚拟机* 虚拟机S, Value* args) {
   //代码块为参数必为闭包
   if (!是否为函数(虚拟机S, args[1])) return false;

   //直接返回函数闭包
   返回值M(args[1]);
}

//null取非
static bool NULL取非(虚拟机* 虚拟机S , Value* args ) {
   返回值M(BOOL_TO_VALUE(true));
}

//null的字符串化
static bool NULL的字符串化(虚拟机* 虚拟机S, Value* args ) {
   字符串对象S* objZiFuChuan = 以字符串创建字符串对象(虚拟机S, "null", 4);
   RET_OBJ(objZiFuChuan);
}

//将字符串转换为数字
static bool 将字符串转换为数字(虚拟机* 虚拟机S, Value* args) {
   if (!是否为字符串(虚拟机S, args[1])) {
      return false;
   }
   
   字符串对象S* objZiFuChuan = VALUE_TO_OBJSTR(args[1]);

   //空字符串返回RETURN_NULL
   if (objZiFuChuan->value.长度 == 0) {
      RET_NULL;
   }

   ASSERT(objZiFuChuan->value.start[objZiFuChuan->value.长度] == '\0', "objZiFuChuan don`t teminate!");

   errno = 0;
   char* endPtr;

   //将字符串转换为double型, 它会自动跳过前面的空白
   double num = strtod(objZiFuChuan->value.start, &endPtr);
   
   //以endPtr是否等于start+length来判断不能转换的字符之后是否全是空白
   while (*endPtr != '\0' && isspace((unsigned char)*endPtr)) {
      endPtr++;   
   }
   
   if (errno == ERANGE) {
      runtime_错误("string too large!");
   }

   //如果字符串中不能转换的字符不全是空白,字符串非法,返回NULL
   if (endPtr < objZiFuChuan->value.start + objZiFuChuan->value.长度) {
      RET_NULL;   
   }

   //至此,检查通过,返回正确结果
   RET_NUM(num);
}

//返回圆周率
static bool 返回圆周率(虚拟机* 虚拟机S , Value* args ) {
   RET_NUM(3.14159265358979323846);
}

#define PRIM_NUM_INFIX(name, operator, type) \
   static bool name(虚拟机* 虚拟机S, Value* args) {\
      if (!是否为数字(虚拟机S, args[1])) {\
	 return false; \
      }\
      RET_##type(VALUE_TO_NUM(args[0]) operator VALUE_TO_NUM(args[1]));\
   }

PRIM_NUM_INFIX(primNumPlus,   +, NUM);
PRIM_NUM_INFIX(primNumMinus,  -, NUM);
PRIM_NUM_INFIX(primNumMul,    *, NUM);
PRIM_NUM_INFIX(primNumDiv,    /, NUM);
PRIM_NUM_INFIX(primNumGt,   >, BOOL);
PRIM_NUM_INFIX(primNumGe,  >=, BOOL);
PRIM_NUM_INFIX(primNumLt,   <, BOOL);
PRIM_NUM_INFIX(primNumLe,  <=, BOOL);
#undef PRIM_NUM_INFIX

 #define PRIM_NUM_BIT(name, operator) \
   static bool name(虚拟机* 虚拟机S , Value* args) {\
      if (!是否为数字(虚拟机S, args[1])) {\
	 return false;\
      }\
      uint32_t leftOperand = VALUE_TO_NUM(args[0]); \
      uint32_t rightOperand = VALUE_TO_NUM(args[1]); \
      RET_NUM(leftOperand operator rightOperand);\
   }

PRIM_NUM_BIT(primNumBitAnd, &);
PRIM_NUM_BIT(primNumBitOr, |);
PRIM_NUM_BIT(primNumBitShiftRight, >>);
PRIM_NUM_BIT(primNumBitShiftLeft, <<);
#undef PRIM_NUM_BIT

//使用数学库函数
#define PRIM_NUM_MATH_FN(name, mathFn) \
   static bool name(虚拟机* 虚拟机S , Value* args) {\
      RET_NUM(mathFn(VALUE_TO_NUM(args[0]))); \
   }

PRIM_NUM_MATH_FN(primNumAbs,	 fabs);
PRIM_NUM_MATH_FN(primNumAcos,	 acos);
PRIM_NUM_MATH_FN(primNumAsin,    asin);
PRIM_NUM_MATH_FN(primNumAtan,    atan);
PRIM_NUM_MATH_FN(primNumCeil,    ceil);
PRIM_NUM_MATH_FN(primNumCos,     cos);
PRIM_NUM_MATH_FN(primNumFloor,   floor);
PRIM_NUM_MATH_FN(primNumNegate,  -);
PRIM_NUM_MATH_FN(primNumSin,     sin);
PRIM_NUM_MATH_FN(primNumSqrt,    sqrt);  //开方
PRIM_NUM_MATH_FN(primNumTan,     tan);
#undef PRIM_NUM_MATH_FN

//这里用fmod实现浮点取模
static bool 浮点数字取模(虚拟机* 虚拟机S , Value* args) {
   if (!是否为数字(虚拟机S, args[1])) {
      return false;
   }
   RET_NUM(fmod(VALUE_TO_NUM(args[0]), VALUE_TO_NUM(args[1])));
}

//数字取反
static bool 数字取反(虚拟机* 虚拟机S , Value* args) {
   RET_NUM(~(uint32_t)VALUE_TO_NUM(args[0]));
}

//[数字from..数字to]
static bool 数字范围(虚拟机* 虚拟机S , Value* args) {
   if (!是否为数字(虚拟机S, args[1])) {
      return false;
   }

   double from = VALUE_TO_NUM(args[0]); 
   double to = VALUE_TO_NUM(args[1]); 
   RET_OBJ(新建范围对象(虚拟机S, from, to));
}

//atan2(args[1])
static bool primNumAtan2(虚拟机* 虚拟机S , Value* args) {
   if (!是否为数字(虚拟机S, args[1])) {
      return false;
   }
   
   RET_NUM(atan2(VALUE_TO_NUM(args[0]), VALUE_TO_NUM(args[1])));
}

//返回小数部分
static bool 数字返回小数部分(虚拟机* 虚拟机S , Value* args) {
   double dummyInteger;
   RET_NUM(modf(VALUE_TO_NUM(args[0]), &dummyInteger));
}

//判断数字是否无穷大,不区分正负无穷大
static bool 数字是否无穷大(虚拟机* 虚拟机S , Value* args) {
   RET_BOOL(isinf(VALUE_TO_NUM(args[0])));  
}

//判断是否为数字
static bool 数字是否为整数(虚拟机* 虚拟机S , Value* args) {
   double num = VALUE_TO_NUM(args[0]);
   //如果是nan(不是一个数字)或无限大的数字就返回false
   if (isnan(num) || isinf(num)) {
      RET_FALSE;
   }
   RET_BOOL(trunc(num) == num);
}

//判断数字是否为nan
static bool 数字是否为nan(虚拟机* 虚拟机S , Value* args) {
   RET_BOOL(isnan(VALUE_TO_NUM(args[0])));
}

//数字转换为字符串
static bool 转换数字为字符串(虚拟机* 虚拟机S , Value* args) {
   RET_OBJ(将数字转换为字符串(虚拟机S, VALUE_TO_NUM(args[0])));
}

//取数字的整数部分
static bool 取数字的整数部分(虚拟机* 虚拟机S , Value* args) {
   double integer;
   modf(VALUE_TO_NUM(args[0]), &integer);
   RET_NUM(integer);
}

//判断两个数字是否相等
static bool 判断两个数字是否相等(虚拟机* 虚拟机S , Value* args) {
   if (!是否为数字(虚拟机S, args[1])) {
      RET_FALSE;
   }

   RET_BOOL(VALUE_TO_NUM(args[0]) == VALUE_TO_NUM(args[1]));
}

//判断两个数字是否不等
static bool 判断两个数字是否不相等(虚拟机* 虚拟机S , Value* args) {
   if (!是否为数字(虚拟机S, args[1])) {
      RET_TRUE;
   }
   RET_BOOL(VALUE_TO_NUM(args[0]) != VALUE_TO_NUM(args[1]));
}

//objZiFuChuan.fromCodePoint(_):从码点建立字符串
static bool 从码点建立字符串(虚拟机* 虚拟机S, Value* args) {

   if (!是否为整数(虚拟机S, args[1])) {
      return false;
   }
   
   int codePoint = (int)VALUE_TO_NUM(args[1]);
   if (codePoint < 0) {
      SET_ERROR_FALSE(虚拟机S, "code point can`t be negetive!");
   }

   if (codePoint > 0x10ffff) {
      SET_ERROR_FALSE(虚拟机S, "code point must be between 0 and 0x10ffff!");
   }
   
   返回值M(从码点创建字符串(虚拟机S, codePoint));
}

//objZiFuChuan+objZiFuChuan: 字符串相加
static bool 字符串相加(虚拟机* 虚拟机S, Value* args) {
   if (!是否为字符串(虚拟机S, args[1])) {
      return false;
   }

   字符串对象S* left = VALUE_TO_OBJSTR(args[0]);
   字符串对象S* right = VALUE_TO_OBJSTR(args[1]);

   uint32_t totalLength = strlen(left->value.start) + strlen(right->value.start);
   //+1是为了结尾的'\0'
   字符串对象S* result = 分配除主类型外还需要额外指定大小的内存M(虚拟机S, 字符串对象S, totalLength + 1);
   if (result == NULL) {
      内存分配_错误("allocate memory failed in runtime!"); 
   }
   初始化对象头(虚拟机S, &result->objHeader, 对象类型_字符串, 虚拟机S->stringClass);
   memcpy(result->value.start, left->value.start, strlen(left->value.start));
   memcpy(result->value.start + strlen(left->value.start), 
	 right->value.start, strlen(right->value.start));
   result->value.start[totalLength] = '\0';
   result->value.长度 = totalLength;
   为字符串计算哈希值并将值存储(result);

   RET_OBJ(result);
}

//objZiFuChuan[_]:用数字或objRange对象做字符串的subscript
static bool 创建字符串下标(虚拟机* 虚拟机S, Value* args) {
   字符串对象S* objZiFuChuan = VALUE_TO_OBJSTR(args[0]);
   //数字和objRange都可以做索引,分别判断
   //若索引是数字,就直接索引1个字符,这是最简单的subscript
   if (VALUE_IS_NUM(args[1])) {
      uint32_t index = 索引是否有效(虚拟机S, args[1], objZiFuChuan->value.长度);
      if (index == UINT32_MAX) {
	 return false; 
      }
      返回值M(用索引处的字符创建字符串对象(虚拟机S, objZiFuChuan, index));
   }

   //索引要么为数字要么为ObjRange,若不是数字就应该为objRange
   if (!VALUE_IS_OBJRANGE(args[1])) {
      SET_ERROR_FALSE(虚拟机S, "下标 should be integer or range!");
   }
   
   //direction是索引的方向,
   //1表示正方向,从前往后.-1表示反方向,从后往前.
   //from若比to大,即从后往前检索字符,direction则为-1
   int direction;

   uint32_t count = objZiFuChuan->value.长度;
   //返回的startIndex是objRange.from在objZiFuChuan.value.start中的下标
   uint32_t startIndex = 计算范围(虚拟机S, VALUE_TO_OBJRANGE(args[1]), &count, &direction);
   if (startIndex == UINT32_MAX) { 
      return false;
   }

   RET_OBJ(以指定起始指定方向和指定数量字符创建字符串(虚拟机S, objZiFuChuan, startIndex, count, direction));
}

//objZiFuChuan.byteAt_():返回指定索引的字节
static bool 返回指定索引的字节(虚拟机* 虚拟机S , Value* args) {
   字符串对象S* objZiFuChuan = VALUE_TO_OBJSTR(args[0]);
   uint32_t index = 索引是否有效(虚拟机S, args[1], objZiFuChuan->value.长度);
   if (index == UINT32_MAX) {
      return false; 
   }
   //故转换为数字返回
   RET_NUM((uint8_t)objZiFuChuan->value.start[index]);
}

//objZiFuChuan.byteCount_:返回字节数
static bool 返回字符串的字节数(虚拟机* 虚拟机S , Value* args) {
   RET_NUM(VALUE_TO_OBJSTR(args[0])->value.长度);
}

//objZiFuChuan.codePointAt_(_):返回指定的CodePoint
static bool 返回指定的码点(虚拟机* 虚拟机S , Value* args) {
   字符串对象S* objZiFuChuan = VALUE_TO_OBJSTR(args[0]);
   uint32_t index = 索引是否有效(虚拟机S, args[1], objZiFuChuan->value.长度);
   if (index == UINT32_MAX) {
      return false; 
   }

   const uint8_t* bytes = (uint8_t*)objZiFuChuan->value.start;
   if ((bytes[index] & 0xc0) == 0x80) {
      //如果index指向的并不是utf8编码的最高字节
      //而是后面的低字节,返回-1提示用户
      RET_NUM(-1);
   }

   //返回解码
   RET_NUM(解码一个经过UTF8编码的字符序列((uint8_t*)objZiFuChuan->value.start + index,
	    objZiFuChuan->value.长度 - index));
}

//objZiFuChuan.contains(_):判断字符串args[0]中是否包含子字符串args[1]
static bool 判断字符串是否包含(虚拟机* 虚拟机S , Value* args) {
   if (!是否为字符串(虚拟机S, args[1])) {
      return false;
   }

   字符串对象S* objZiFuChuan = VALUE_TO_OBJSTR(args[0]);
   字符串对象S* pattern = VALUE_TO_OBJSTR(args[1]);
   RET_BOOL(查找字符串(objZiFuChuan, pattern) != -1);
}

//objZiFuChuan.endsWith(_): 返回字符串是否以args[1]为结束
static bool 字符串是否以参数为结束(虚拟机* 虚拟机S , Value* args) {
   if (!是否为字符串(虚拟机S, args[1])) {
      return false;
   }

   字符串对象S* objZiFuChuan = VALUE_TO_OBJSTR(args[0]);
   字符串对象S* pattern = VALUE_TO_OBJSTR(args[1]);

   //若pattern比源串还长,源串必然不包括pattern
   if (pattern->value.长度 > objZiFuChuan->value.长度) {
      RET_FALSE;
   }

   char* cmpIdx = objZiFuChuan->value.start +
      objZiFuChuan->value.长度 - pattern->value.长度;
   RET_BOOL(memcmp(cmpIdx, pattern->value.start, pattern->value.长度) == 0);
}

//objZiFuChuan.indexOf(_):检索字符串args[0]中子串args[1]的起始下标
static bool 检索字符串中子字符串的起始下标(虚拟机* 虚拟机S , Value* args) {
   if (!是否为字符串(虚拟机S, args[1])) {
      return false;
   }

   字符串对象S* objZiFuChuan = VALUE_TO_OBJSTR(args[0]);
   字符串对象S* pattern = VALUE_TO_OBJSTR(args[1]);

   //若pattern比源串还长,源串必然不包括pattern
   if (pattern->value.长度 > objZiFuChuan->value.长度) {
      RET_FALSE;
   }
   
   int index = 查找字符串(objZiFuChuan, pattern);
   RET_NUM(index);
}

//objZiFuChuan.iterate(_):返回下一个utf8字符(不是字节)的迭代器
static bool 返回下一个UTF8字符的迭代器(虚拟机* 虚拟机S , Value* args) {
   字符串对象S* objZiFuChuan = VALUE_TO_OBJSTR(args[0]);

   //如果是第一次迭代 迭代索引肯定为空
   if (VALUE_IS_NULL(args[1])) {
      if (objZiFuChuan->value.长度 == 0) {
	 RET_FALSE;
      }
      RET_NUM(0);
   }

   //迭代器必须是正整数
   if (!是否为整数(虚拟机S, args[1])){
      return false;
   }
   
   double iter = VALUE_TO_NUM(args[1]);
   if (iter < 0) {   
     RET_FALSE;
   }

   uint32_t index = (uint32_t)iter;
   do {
      index++;

      //到了结尾就返回false,表示迭代完毕
      if (index >= objZiFuChuan->value.长度) RET_FALSE;

      //读取连续的数据字节,直到下一个Utf8的高字节
   } while ((objZiFuChuan->value.start[index] & 0xc0) == 0x80);  

   RET_NUM(index);
}

//objZiFuChuan.iterateByte_(_): 迭代索引,内部使用
static bool 字符串迭代索引(虚拟机* 虚拟机S , Value* args) {
   字符串对象S* objZiFuChuan = VALUE_TO_OBJSTR(args[0]);

   //如果是第一次迭代 迭代索引肯定为空 直接返回索引0
   if (VALUE_IS_NULL(args[1])) {
      if (objZiFuChuan->value.长度 == 0) {
	 RET_FALSE;
      }
      RET_NUM(0);
   }

   //迭代器必须是正整数
   if (!是否为整数(虚拟机S, args[1])) {
      return false;
   }

   double iter = VALUE_TO_NUM(args[1]);

   if (iter < 0) {   
     RET_FALSE;
   }

   uint32_t index = (uint32_t)iter;
   index++; //移进到下一个字节的索引
   if (index >= objZiFuChuan->value.长度) {
      RET_FALSE;
   }
   
   RET_NUM(index);
}

//objZiFuChuan.iteratorValue(_):返回迭代器对应的value
static bool 字符串迭代器对用的值(虚拟机* 虚拟机S, Value* args) {
   字符串对象S* objZiFuChuan = VALUE_TO_OBJSTR(args[0]);
   uint32_t index = 索引是否有效(虚拟机S, args[1], objZiFuChuan->value.长度);
   if (index == UINT32_MAX) {
      return false; 
   }
   返回值M(用索引处的字符创建字符串对象(虚拟机S, objZiFuChuan, index));
}

//objZiFuChuan.startsWith(_): 返回args[0]是否以args[1]为起始
static bool 字符串是否以什么为起始(虚拟机* 虚拟机S , Value* args) {
   if (!是否为字符串(虚拟机S, args[1])) {
      return false;
   }

   字符串对象S* objZiFuChuan = VALUE_TO_OBJSTR(args[0]);
   字符串对象S* pattern = VALUE_TO_OBJSTR(args[1]);

   //若pattern比源串还长,源串必然不包括pattern,
   //因此不可能以pattern为起始
   if (pattern->value.长度 > objZiFuChuan->value.长度) {
      RET_FALSE;
   }

   RET_BOOL(memcmp(objZiFuChuan->value.start, 
	    pattern->value.start, pattern->value.长度) == 0);
}

//objZiFuChuan.toZiFuChuan:获得自己的字符串
static bool 获取字符串自己的字符串(虚拟机* 虚拟机S , Value* args) {
   返回值M(args[0]);
}

//objList.new():创建1个新的liist
static bool 创建一个新的list(虚拟机* 虚拟机S, Value* args ) {
   RET_OBJ(新建list对象(虚拟机S, 0));
}

//objList[_]:索引list元素
static bool 索引list元素(虚拟机* 虚拟机S, Value* args) {
   list对象S* objList = VALUE_TO_OBJLIST(args[0]);

   //数字和objRange都可以做索引,分别判断
   //若索引是数字,就直接索引1个字符,这是最简单的subscript
   if (VALUE_IS_NUM(args[1])) {
      uint32_t index = 索引是否有效(虚拟机S, args[1], objList->elements.count);
      if (index == UINT32_MAX) {
	 return false; 
      }
      返回值M(objList->elements.数据缓冲区[index]);
   }

   //索引要么为数字要么为ObjRange,若不是数字就应该为objRange
   if (!VALUE_IS_OBJRANGE(args[1])) {
      SET_ERROR_FALSE(虚拟机S, "下标 should be integer or range!");  
   }

   int direction;

   uint32_t count = objList->elements.count;

   //返回的startIndex是objRange.from在objList.elements.data中的下标
   uint32_t startIndex = 计算范围(虚拟机S, VALUE_TO_OBJRANGE(args[1]), &count, &direction);

   //新建一个list 存储该range在原来list中索引的元素
   list对象S* result = 新建list对象(虚拟机S, count);  
   uint32_t idx = 0;
   while (idx < count) {
      //direction为-1表示从后往前倒序赋值
      //如var l = [a,b,c,d,e,f,g]; l[5..3]表示[f,e,d]
      result->elements.数据缓冲区[idx] = objList->elements.数据缓冲区[startIndex + idx * direction];   
      idx++;
   }
   RET_OBJ(result);
}

//objList[_]=(_):只支持数字做为subscript
static bool list只支持数字作为下标(虚拟机* 虚拟机S , Value* args) {  
   //获取对象
   list对象S* objList = VALUE_TO_OBJLIST(args[0]);

   //获取subscript
   uint32_t index = 索引是否有效(虚拟机S, args[1], objList->elements.count);
   if (index == UINT32_MAX) {
      return false; 
   }

   //直接赋值
   objList->elements.数据缓冲区[index] = args[2];

   返回值M(args[2]); //把参数2做为返回值
}

//objList.add(_):直接追加到list中
static bool 直接追加到list中(虚拟机* 虚拟机S, Value* args) {
   list对象S* objList = VALUE_TO_OBJLIST(args[0]);
   ValueBufferAdd(虚拟机S, &objList->elements, args[1]);
   返回值M(args[1]); //把参数1做为返回值
}

//objList.addCore_(_):编译内部使用的,用于编译列表直接量
static bool 编译list直接量(虚拟机* 虚拟机S, Value* args) {
   list对象S* objList = VALUE_TO_OBJLIST(args[0]);
   ValueBufferAdd(虚拟机S, &objList->elements, args[1]);  
   返回值M(args[0]); //返回列表自身
}

//objList.clear():清空list
static bool 清空list(虚拟机* 虚拟机S, Value* args) {
   list对象S* objList = VALUE_TO_OBJLIST(args[0]);
   ValueBufferClear(虚拟机S, &objList->elements);
   RET_NULL;
}

//objList.count:返回list中元素个数
static bool 返回list元素个数(虚拟机* 虚拟机S , Value* args) {
   RET_NUM(VALUE_TO_OBJLIST(args[0])->elements.count);
}

//objList.insert(_,_):插入元素
static bool list插入元素(虚拟机* 虚拟机S, Value* args) {
   list对象S* objList = VALUE_TO_OBJLIST(args[0]);
   //+1确保可以在最后插入
   uint32_t index = 索引是否有效(虚拟机S, args[1], objList->elements.count + 1);
   if (index == UINT32_MAX) {
      return false; 
   }
   在list对象index索引处插入值(虚拟机S, objList, index, args[2]);
   返回值M(args[2]);  //参数2做为返回值
}

//objList.iterate(_):迭代list
static bool 迭代list(虚拟机* 虚拟机S, Value* args) {
   list对象S* objList = VALUE_TO_OBJLIST(args[0]);

   //如果是第一次迭代 迭代索引肯定为空 直接返回索引0
   if (VALUE_IS_NULL(args[1])) {
      if (objList->elements.count == 0) {
	 RET_FALSE;
      }
      RET_NUM(0);
   }

   //确保迭代器是整数
   if (!是否为整数(虚拟机S, args[1])) {
      return false; 
   }

   double iter = VALUE_TO_NUM(args[1]);
   //如果迭代完了就终止
   if (iter < 0 || iter >= objList->elements.count - 1) {
      RET_FALSE;
   }
   
   RET_NUM(iter + 1);   //返回下一个
}

//objList.iteratorValue(_):返回迭代值
static bool 返回list迭代值(虚拟机* 虚拟机S, Value* args) {
   //获取实例对象
   list对象S* objList = VALUE_TO_OBJLIST(args[0]);
   
   uint32_t index = 索引是否有效(虚拟机S, args[1], objList->elements.count);
   if (index == UINT32_MAX) {
      return false; 
   }

   返回值M(objList->elements.数据缓冲区[index]);
}

//objList.removeAt(_):删除指定位置的元素
static bool 删除list中指定位置的元素(虚拟机* 虚拟机S, Value* args) {
   //获取实例对象
   list对象S* objList = VALUE_TO_OBJLIST(args[0]);

   uint32_t index = 索引是否有效(虚拟机S, args[1], objList->elements.count);
   if (index == UINT32_MAX) {
      return false; 
   }

   返回值M(删除list中索引值为index的元素(虚拟机S, objList, index));
}

//objMap.new():创建map对象
static bool 创建map对象(虚拟机* 虚拟机S, Value* args ) {
   RET_OBJ(新建map对象(虚拟机S));
}

//objMap[_]:返回map[key]对应的value
static bool 返回map键对应的值(虚拟机* 虚拟机S, Value* args) {
   //校验key的合法性
   if (!key是否合法(虚拟机S, args[1])) {
      return false;  //出错了,切换线程
   }

   //获得map对象实例
   map对象S* objMap = VALUE_TO_OBJMAP(args[0]); 

   //从map中查找key(args[1])对应的value
   Value value = 在map中查找key对应的value(objMap, args[1]);

   //若没有相应的key则返回NULL
   if (VALUE_IS_UNDEFINED(value)) {
      RET_NULL;
   }

   返回值M(value);
}

//objMap[_]=(_):map[key]=value
static bool 设置map键setter(虚拟机* 虚拟机S, Value* args) {
   //校验key的合法性
   if (!key是否合法(虚拟机S, args[1])) {
      return false;  //出错了,切换线程
   }

   //获得map对象实例
   map对象S* objMap = VALUE_TO_OBJMAP(args[0]); 

   //在map中将key和value关联
   //即map[key]=value
   在map中实现key与value的关联(虚拟机S, objMap, args[1], args[2]);

   返回值M(args[2]); //返回value
}

//objMap.addCore_(_,_):编译器编译map字面量时内部使用的,
//在map中添加(key-value)对儿并返回map自身
static bool 编译map字面量(虚拟机* 虚拟机S, Value* args) {
   if (!key是否合法(虚拟机S, args[1])) {
      return false;  //出错了,切换线程
   }

   //获得map对象实例
   map对象S* objMap = VALUE_TO_OBJMAP(args[0]); 

   //在map中将key和value关联
   //即map[key]=value
   在map中实现key与value的关联(虚拟机S, objMap, args[1], args[2]);

   返回值M(args[0]);  //返回map对象自身
}

//objMap.clear():清除map
static bool 清除map(虚拟机* 虚拟机S, Value* args) {
   回收map中entry占用的空间(虚拟机S, VALUE_TO_OBJMAP(args[0]));
   RET_NULL;
}

//objMap.containsKey(_):判断map即args[0]是否包含key即args[1]
static bool map是否包含键(虚拟机* 虚拟机S, Value* args) {
   if (!key是否合法(虚拟机S, args[1])) {
      return false;  //出错了,切换线程
   }

   //直接去get该key,判断是否get成功
   RET_BOOL(!VALUE_IS_UNDEFINED(在map中查找key对应的value(VALUE_TO_OBJMAP(args[0]), args[1])));
}

//objMap.count:返回map中entry个数
static bool map中entry个数(虚拟机* 虚拟机S , Value* args) {
   RET_NUM(VALUE_TO_OBJMAP(args[0])->count);
}

//objMap.remove(_):删除map[key] map是args[0] key是args[1]
static bool 删除map指定键对应值(虚拟机* 虚拟机S, Value* args) {
   if (!key是否合法(虚拟机S, args[1])) {
      return false;  //出错了,切换线程
   }

   返回值M(删除map中的key(虚拟机S, VALUE_TO_OBJMAP(args[0]), args[1]));
}

//objMap.iterate_(_):迭代map中的entry,
//返回entry的索引供keyIteratorValue_和valueIteratorValue_做迭代器
static bool 迭代map中entry(虚拟机* 虚拟机S, Value* args) {
   //获得map对象实例
   map对象S* objMap = VALUE_TO_OBJMAP(args[0]); 

   //map中若空则返回false不可迭代
   if (objMap->count == 0) {
      RET_FALSE; 
   }

   //若没有传入迭代器,迭代默认是从第0个entry开始
   uint32_t index = 0;  

   //若不是第一次迭代,传进了迭代器
   if (!VALUE_IS_NULL(args[1])) {
      //iter必须为整数
      if (!是否为整数(虚拟机S, args[1])) {
	 //本线程出错了,返回false是为了切换到下一线
	 return false;
      }

      //迭代器不能小0
      if (VALUE_TO_NUM(args[1]) < 0) {
	 RET_FALSE; 
      }

      index = (uint32_t)VALUE_TO_NUM(args[1]);
      //迭代器不能越界
      if (index >= objMap->数组容量) {
	 RET_FALSE;  
      }

      index++;  //更新迭代器
   }

   //返回下一个正在使用(有效)的entry
   while (index < objMap->数组容量) {
      //entries是个数组, 元素是哈希槽,
      //哈希值散布在这些槽中并不连续,因此逐个判断槽位是否在用
      if (!VALUE_IS_UNDEFINED(objMap->entries[index].key)) {
	 RET_NUM(index);    //返回entry索引
      }
      index++;
   }
   
   //若没有有效的entry了就返回false,迭代结束
   RET_FALSE;
}

//objMap.keyIteratorValue_(_): key=map.keyIteratorValue(iter)
static bool map键迭代值(虚拟机* 虚拟机S, Value* args) {
   map对象S* objMap = VALUE_TO_OBJMAP(args[0]);
   
   uint32_t index = 索引是否有效(虚拟机S, args[1], objMap->数组容量);
   if (index == UINT32_MAX) {
      return false; 
   }

   Entry* entry = &objMap->entries[index];
   if (VALUE_IS_UNDEFINED(entry->key)) {
     SET_ERROR_FALSE(虚拟机S, "invalid iterator!");
   }

   //返回该key
   返回值M(entry->key);   
}

//objMap.valueIteratorValue_(_): 
//value = map.valueIteratorValue_(iter)
static bool map值迭代值(虚拟机* 虚拟机S, Value* args) {
   map对象S* objMap = VALUE_TO_OBJMAP(args[0]);
   
   uint32_t index = 索引是否有效(虚拟机S, args[1], objMap->数组容量);
   if (index == UINT32_MAX) {
      return false; 
   }

   Entry* entry = &objMap->entries[index];
   if (VALUE_IS_UNDEFINED(entry->key)) {
     SET_ERROR_FALSE(虚拟机S, "invalid iterator!");
   }

   //返回该key
   返回值M(entry->value);   
}

//objRange.from: 返回range的from
static bool 返回范围的起始值(虚拟机* 虚拟机S , Value* args) {
   RET_NUM(VALUE_TO_OBJRANGE(args[0])->from);
}

//objRange.to: 返回range的to
static bool 返回范围的结束值(虚拟机* 虚拟机S , Value* args) {
   RET_NUM(VALUE_TO_OBJRANGE(args[0])->to);
}

//objRange.min: 返回range中from和to较小的值
static bool 返回范围起始和结束较小的值(虚拟机* 虚拟机S , Value* args) {
   范围对象S* objRange = VALUE_TO_OBJRANGE(args[0]);
   RET_NUM(fmin(objRange->from, objRange->to));
}

//objRange.max: 返回range中from和to较大的值
static bool 返回范围起始和结束较大的值(虚拟机* 虚拟机S , Value* args) {
   范围对象S* objRange = VALUE_TO_OBJRANGE(args[0]);
   RET_NUM(fmax(objRange->from, objRange->to));
}

//objRange.iterate(_): 迭代range中的值,并不索引
static bool 迭代范围中的值(虚拟机* 虚拟机S, Value* args) {
   范围对象S* objRange = VALUE_TO_OBJRANGE(args[0]);

   //若未提供iter说明是第一次迭代,因此返回range->from
   if (VALUE_IS_NULL(args[1])) {
      RET_NUM(objRange->from);
   }

   //迭代器必须是数字
   if (!是否为数字(虚拟机S, args[1])) {
      return false;
   }

   //获得迭代器
   double iter = VALUE_TO_NUM(args[1]);

   //若是正方向
   if (objRange->from < objRange->to) {
      iter++;
      if (iter > objRange->to) {
	 RET_FALSE;
      }
   } else {  //若是反向迭代
      iter--; 
      if (iter < objRange->to) {
	 RET_FALSE;
      }
   }

   RET_NUM(iter);
}

//objRange.iteratorValue(_): range的迭代就是range中从from到to之间的值
//因此直接返回迭代器就是range的值
static bool 直接返回迭代器(虚拟机* 虚拟机S , Value* args) {
   范围对象S* objRange = VALUE_TO_OBJRANGE(args[0]);
   double value = VALUE_TO_NUM(args[1]);

   //确保args[1]在from和to的范围中
   //若是正方向
   if (objRange->from < objRange->to) {
      if (value >= objRange->from && value <= objRange->to) {
	 返回值M(args[1]); 
      }
   } else {  //若是反向迭代
      if (value <= objRange->from && value >= objRange->to) {
	 返回值M(args[1]); 
      }
   }
   RET_FALSE;
}

//System.clock: 返回以秒为单位的系统时钟
static bool 返回以秒为单位的系统时钟(虚拟机* 虚拟机S , Value* args ) {
   RET_NUM((double)time(NULL));
}

//System.gc(): 启动gc
static bool 启动系统垃圾回收器(虚拟机* 虚拟机S, Value* args) {
   运行垃圾回收器(虚拟机S);
   RET_NULL;
}

//System.importModule(_): 导入并编译模块args[1],把模块挂载到vm->allModules
static bool 系统导入模块(虚拟机* 虚拟机S, Value* args) {
   if (!是否为字符串(虚拟机S, args[1])) { //模块名为字符串
      return false;
   }

   //导入模块name并编译 把模块挂载到vm->allModules
   Value result = 导入模块(虚拟机S, args[1]);

   //若已经导入过则返回NULL_VAL
   if (VALUE_IS_NULL(result)) {
      RET_NULL;
   }

   //若编译过程中出了问题,切换到下一线程
   if (!VALUE_IS_NULL(虚拟机S->当前正在执行的线程->errorObj)) {
      return false;
   }

   //回收1个slot空间
   虚拟机S->当前正在执行的线程->esp--;

   线程对象S* nextThread = VALUE_TO_OBJTHREAD(result);
   nextThread->caller = 虚拟机S->当前正在执行的线程;
   虚拟机S->当前正在执行的线程 = nextThread;
   //返回false,vm会切换到此新加载模块的线程
   return false;
}

//System.getModuleVariable(_,_): 获取模块args[1]中的模块变量args[2]
static bool 系统获取模块变量(虚拟机* 虚拟机S, Value* args) {
   if (!是否为字符串(虚拟机S, args[1])) {
      return false;
   }

   if (!是否为字符串(虚拟机S, args[2])) {
      return false;
   }
   
   Value result = 获取模块变量(虚拟机S, args[1], args[2]);
   if (VALUE_IS_NULL(result)) {
      //出错了,给vm返回false以切换线程
      return false;
   }

   返回值M(result);
}

//System.writeZiFuChuan_(_): 输出字符串args[1]
static bool 系统输出字符串(虚拟机* 虚拟机S , Value* args) {
   字符串对象S* objZiFuChuan = VALUE_TO_OBJSTR(args[1]);
   ASSERT(objZiFuChuan->value.start[objZiFuChuan->value.长度] == '\0', "string isn`t terminated!");
   输出字符串(objZiFuChuan->value.start);
   返回值M(args[1]);
}

虚拟机执行结果S 执行模块(虚拟机* 虚拟机S, Value moduleName, const char* moduleCode)
{
   线程对象S* objThread = 载入模块(虚拟机S, moduleName, moduleCode);
   return 执行指令(虚拟机S, objThread);
}

//table中查找符号symbol 找到后返回索引,否则返回-1
int 从符号表获取符号索引(SymbolTable* table, const char* symbol, uint32_t 长度) {
   ASSERT(长度 != 0, "长度 of symbol is 0!");
   uint32_t index = 0;
   while (index < table->count) {
      if (长度 == table->数据缓冲区[index].长度 &&
	    memcmp(table->数据缓冲区[index].str, symbol, 长度) == 0) {
	 return index;
      }
      index++;
   }
   return -1;
}

//往table中添加符号symbol,返回其索引
int 添加符号(虚拟机* 虚拟机S, SymbolTable* table, const char* symbol, uint32_t 长度) {
   ASSERT(长度 != 0, "长度 of symbol is 0!");
   ZiFuChuan string;
   string.str = 分配数组内存M(虚拟机S, char, 长度 + 1);
   memcpy(string.str, symbol, 长度);
   string.str[长度] = '\0';
   string.长度 = 长度;
   ZiFuChuanBufferAdd(虚拟机S, table, string);
   return table->count - 1;
}

//确保符号已添加到符号表
int 确保符号已经添加到符号表(虚拟机* 虚拟机S, SymbolTable* table, const char* symbol, uint32_t 长度) {
   int symbolIndex = 从符号表获取符号索引(table, symbol, 长度);
   if (symbolIndex == -1) {
      return 添加符号(虚拟机S, table, symbol, 长度);
   }
   return symbolIndex;
}

//定义类
static Class* 定义类(虚拟机* 虚拟机S, 模块对象S* objModule, const char* name) {
   //1先创建类
   Class* class = 新建一个裸类(虚拟机S, name, 0);

   //2把类做为普通变量在模块中定义
   Value vTmp;
   SET_VALUE_OBJ(&vTmp, class);
   定义模块变量(虚拟机S, objModule, name, strlen(name), vTmp);
   //定义模块变量(虚拟机S, objModule, name, strlen(name), OBJ_TO_VALUE(class));
   return class;
}

//使class->methods[index]=method
void 绑定方法(虚拟机* 虚拟机S, Class* class, uint32_t index, Method method) {
   if (index >= class->methods.count) {
      Method emptyPad = {方法类型_空类型, {0}};
      MethodBufferFillWrite(虚拟机S, &class->methods, emptyPad, index - class->methods.count + 1); 
   }
   class->methods.数据缓冲区[index] = method;
}

//绑定基类
void 绑定基类(虚拟机* 虚拟机S, Class* subClass, Class* superClass) {
   subClass->superClass = superClass;

   //继承基类属性数
   subClass->fieldNum += superClass->fieldNum;

   //继承基类方法
   uint32_t idx = 0;
   while (idx < superClass->methods.count) {
      绑定方法(虚拟机S, subClass, idx, superClass->methods.数据缓冲区[idx]); 
      idx++;
   }
}

//绑定fn.call的重载
static void 绑定函数调用的重载(虚拟机* 虚拟机S, const char* sign) {
   uint32_t index = 确保符号已经添加到符号表(虚拟机S, &虚拟机S->所有类的方法名称, sign, strlen(sign));
   //构造method
   Method method = {方法类型_函数对象的调用, {0}};
   绑定方法(虚拟机S, 虚拟机S->fnClass, index, method);
}

//编译核心模块
void 创建核心模块(虚拟机* 虚拟机S) {

   //核心模块不需要名字,模块也允许名字为空
   模块对象S* coreModule = 新建对象模块(虚拟机S, NULL);

   将obj作为临时根对象(虚拟机S, (对象头S*)coreModule);
   //创建核心模块,录入到vm->allModules
   Value vTmp;
   SET_VALUE_OBJ(&vTmp, coreModule);
   在map中实现key与value的关联(虚拟机S, 虚拟机S->allModules, CORE_MODULE,  vTmp);
   //在map中实现key与value的关联(虚拟机S, 虚拟机S->allModules, CORE_MODULE, OBJ_TO_VALUE(coreModule));

   去掉临时根对象(虚拟机S);

   //创建object类并绑定方法
   虚拟机S->objectClass = 定义类(虚拟机S, coreModule, "object");
   绑定方法到指定的类M(虚拟机S->objectClass, "!", 原对象取反);
   绑定方法到指定的类M(虚拟机S->objectClass, "==(_)", 原对象是否相等);
   绑定方法到指定的类M(虚拟机S->objectClass, "!=(_)", 原对象是否不相等);
   绑定方法到指定的类M(虚拟机S->objectClass, "is(_)", 原对象是否为子类);
   绑定方法到指定的类M(虚拟机S->objectClass, "toZiFuChuan", 返回参数所属类的名字);
   绑定方法到指定的类M(虚拟机S->objectClass, "type", 返回对象的类);

   //定义classOfClass类,它是所有meta类的meta类和基类
   虚拟机S->classOfClass = 定义类(虚拟机S, coreModule, "class");

   //objectClass是任何类的基类
   绑定基类(虚拟机S, 虚拟机S->classOfClass, 虚拟机S->objectClass);

   绑定方法到指定的类M(虚拟机S->classOfClass, "name", 返回类的名称);
   绑定方法到指定的类M(虚拟机S->classOfClass, "supertype", 返回对象的基类);
   绑定方法到指定的类M(虚拟机S->classOfClass, "toZiFuChuan", 返回类名为字符串);

   //定义object类的元信息类objectMetaclass,它无须挂载到vm
   Class* objectMetaclass = 定义类(虚拟机S, coreModule, "objectMeta");
   
   //classOfClass类是所有meta类的meta类和基类
   绑定基类(虚拟机S, objectMetaclass, 虚拟机S->classOfClass);

   //类型比较
   绑定方法到指定的类M(objectMetaclass, "same(_,_)", primObjectmetaSame);

   //绑定各自的meta类
   虚拟机S->objectClass->objHeader.class = objectMetaclass;
   objectMetaclass->objHeader.class = 虚拟机S->classOfClass;
   虚拟机S->classOfClass->objHeader.class = 虚拟机S->classOfClass; //元信息类回路,meta类终点
   
   //执行核心模块
   执行模块(虚拟机S, CORE_MODULE, coreModuleCode);
   
   //Bool类定义在core.script.inc中,将其挂载Bool类到vm->boolClass
   虚拟机S->boolClass = VALUE_TO_CLASS(获取核心类的值(coreModule, "Bool"));
   绑定方法到指定的类M(虚拟机S->boolClass, "toZiFuChuan", 返回布尔的字符串形式);
   绑定方法到指定的类M(虚拟机S->boolClass, "!", 布尔值取反);

   //Thread类也是在core.script.inc中定义的,
   //将其挂载到vm->threadClass并补充原生方法
   虚拟机S->threadClass = VALUE_TO_CLASS(获取核心类的值(coreModule, "Thread"));
   //以下是类方法
   绑定方法到指定的类M(虚拟机S->threadClass->objHeader.class, "new(_)", 创建线程实例);
   绑定方法到指定的类M(虚拟机S->threadClass->objHeader.class, "abort(_)", 以错误信息退出线程);
   绑定方法到指定的类M(虚拟机S->threadClass->objHeader.class, "current", 返回当前的线程);
   绑定方法到指定的类M(虚拟机S->threadClass->objHeader.class, "suspend()", 线程挂起);
   绑定方法到指定的类M(虚拟机S->threadClass->objHeader.class, "yield(_)", 线程带参数让出CPU);
   绑定方法到指定的类M(虚拟机S->threadClass->objHeader.class, "yield()", 线程无参数让出CPU);
   //以下是实例方法
   绑定方法到指定的类M(虚拟机S->threadClass, "call()", 无参数线程调用);
   绑定方法到指定的类M(虚拟机S->threadClass, "call(_)", 带参数线程调用);
   绑定方法到指定的类M(虚拟机S->threadClass, "isDone", 线程是否运行完成);

   //绑定函数类
   虚拟机S->fnClass = VALUE_TO_CLASS(获取核心类的值(coreModule, "Fn"));
   绑定方法到指定的类M(虚拟机S->fnClass->objHeader.class, "new(_)", 创建一个函数对象);

   //绑定call的重载方法
   绑定函数调用的重载(虚拟机S, "call()");
   绑定函数调用的重载(虚拟机S, "call(_)");
   绑定函数调用的重载(虚拟机S, "call(_,_)");
   绑定函数调用的重载(虚拟机S, "call(_,_,_)");
   绑定函数调用的重载(虚拟机S, "call(_,_,_,_)");
   绑定函数调用的重载(虚拟机S, "call(_,_,_,_,_)");
   绑定函数调用的重载(虚拟机S, "call(_,_,_,_,_,_)");
   绑定函数调用的重载(虚拟机S, "call(_,_,_,_,_,_,_)");
   绑定函数调用的重载(虚拟机S, "call(_,_,_,_,_,_,_,_)");
   绑定函数调用的重载(虚拟机S, "call(_,_,_,_,_,_,_,_,_)");
   绑定函数调用的重载(虚拟机S, "call(_,_,_,_,_,_,_,_,_,_)");
   绑定函数调用的重载(虚拟机S, "call(_,_,_,_,_,_,_,_,_,_,_)");
   绑定函数调用的重载(虚拟机S, "call(_,_,_,_,_,_,_,_,_,_,_,_)");
   绑定函数调用的重载(虚拟机S, "call(_,_,_,_,_,_,_,_,_,_,_,_,_)");
   绑定函数调用的重载(虚拟机S, "call(_,_,_,_,_,_,_,_,_,_,_,_,_,_)");
   绑定函数调用的重载(虚拟机S, "call(_,_,_,_,_,_,_,_,_,_,_,_,_,_,_)");
   绑定函数调用的重载(虚拟机S, "call(_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_)");

   //绑定Null类的方法
   虚拟机S->nullClass = VALUE_TO_CLASS(获取核心类的值(coreModule, "Null"));
   绑定方法到指定的类M(虚拟机S->nullClass, "!", NULL取非);
   绑定方法到指定的类M(虚拟机S->nullClass, "toZiFuChuan", NULL的字符串化);

   //绑定num类方法
   虚拟机S->numClass = VALUE_TO_CLASS(获取核心类的值(coreModule, "Num"));
   //类方法
   绑定方法到指定的类M(虚拟机S->numClass->objHeader.class, "fromZiFuChuan(_)", 将字符串转换为数字);
   绑定方法到指定的类M(虚拟机S->numClass->objHeader.class, "pi", 返回圆周率);
   //实例方法
   绑定方法到指定的类M(虚拟机S->numClass, "+(_)", primNumPlus);
   绑定方法到指定的类M(虚拟机S->numClass, "-(_)", primNumMinus);
   绑定方法到指定的类M(虚拟机S->numClass, "*(_)", primNumMul);
   绑定方法到指定的类M(虚拟机S->numClass, "/(_)", primNumDiv);
   绑定方法到指定的类M(虚拟机S->numClass, ">(_)", primNumGt);
   绑定方法到指定的类M(虚拟机S->numClass, ">=(_)", primNumGe);
   绑定方法到指定的类M(虚拟机S->numClass, "<(_)", primNumLt);
   绑定方法到指定的类M(虚拟机S->numClass, "<=(_)", primNumLe);

   //位运算
   绑定方法到指定的类M(虚拟机S->numClass, "&(_)", primNumBitAnd);
   绑定方法到指定的类M(虚拟机S->numClass, "|(_)", primNumBitOr);
   绑定方法到指定的类M(虚拟机S->numClass, ">>(_)", primNumBitShiftRight);
   绑定方法到指定的类M(虚拟机S->numClass, "<<(_)", primNumBitShiftLeft);
   //以上都是通过rules中INFIX_OPERATOR来解析的

   //下面大多数方法是通过rules中'.'对应的led(调用的入口)来解析,
   //少数符号依然是INFIX_OPERATOR解析
   绑定方法到指定的类M(虚拟机S->numClass, "abs", primNumAbs);
   绑定方法到指定的类M(虚拟机S->numClass, "acos", primNumAcos);
   绑定方法到指定的类M(虚拟机S->numClass, "asin", primNumAsin);
   绑定方法到指定的类M(虚拟机S->numClass, "atan", primNumAtan);
   绑定方法到指定的类M(虚拟机S->numClass, "ceil", primNumCeil);
   绑定方法到指定的类M(虚拟机S->numClass, "cos", primNumCos);
   绑定方法到指定的类M(虚拟机S->numClass, "floor", primNumFloor);
   绑定方法到指定的类M(虚拟机S->numClass, "-", primNumNegate);
   绑定方法到指定的类M(虚拟机S->numClass, "sin", primNumSin);
   绑定方法到指定的类M(虚拟机S->numClass, "sqrt", primNumSqrt);
   绑定方法到指定的类M(虚拟机S->numClass, "tan", primNumTan);
   绑定方法到指定的类M(虚拟机S->numClass, "%(_)", 浮点数字取模);
   绑定方法到指定的类M(虚拟机S->numClass, "~", 数字取反);
   绑定方法到指定的类M(虚拟机S->numClass, "..(_)", 数字范围);
   绑定方法到指定的类M(虚拟机S->numClass, "atan(_)", primNumAtan2);
   绑定方法到指定的类M(虚拟机S->numClass, "fraction", 数字返回小数部分);
   绑定方法到指定的类M(虚拟机S->numClass, "isInfinity", 数字是否无穷大);
   绑定方法到指定的类M(虚拟机S->numClass, "isInteger", 数字是否为整数);
   绑定方法到指定的类M(虚拟机S->numClass, "isNan", 数字是否为nan);
   绑定方法到指定的类M(虚拟机S->numClass, "toZiFuChuan", 转换数字为字符串);
   绑定方法到指定的类M(虚拟机S->numClass, "truncate", 取数字的整数部分);
   绑定方法到指定的类M(虚拟机S->numClass, "==(_)", 判断两个数字是否相等);
   绑定方法到指定的类M(虚拟机S->numClass, "!=(_)", 判断两个数字是否不相等);

   //字符串类
   虚拟机S->stringClass = VALUE_TO_CLASS(获取核心类的值(coreModule, "ZiFuChuan"));
   绑定方法到指定的类M(虚拟机S->stringClass->objHeader.class, "fromCodePoint(_)", 从码点建立字符串);
   绑定方法到指定的类M(虚拟机S->stringClass, "+(_)", 字符串相加);
   绑定方法到指定的类M(虚拟机S->stringClass, "[_]", 创建字符串下标);
   绑定方法到指定的类M(虚拟机S->stringClass, "byteAt_(_)", 返回指定索引的字节);
   绑定方法到指定的类M(虚拟机S->stringClass, "byteCount_", 返回字符串的字节数);
   绑定方法到指定的类M(虚拟机S->stringClass, "codePointAt_(_)", 返回指定的码点);
   绑定方法到指定的类M(虚拟机S->stringClass, "contains(_)", 判断字符串是否包含);
   绑定方法到指定的类M(虚拟机S->stringClass, "endsWith(_)", 字符串是否以参数为结束);
   绑定方法到指定的类M(虚拟机S->stringClass, "indexOf(_)", 检索字符串中子字符串的起始下标);
   绑定方法到指定的类M(虚拟机S->stringClass, "iterate(_)", 返回下一个UTF8字符的迭代器);
   绑定方法到指定的类M(虚拟机S->stringClass, "iterateByte_(_)", 字符串迭代索引);
   绑定方法到指定的类M(虚拟机S->stringClass, "iteratorValue(_)", 字符串迭代器对用的值);
   绑定方法到指定的类M(虚拟机S->stringClass, "startsWith(_)", 字符串是否以什么为起始);
   绑定方法到指定的类M(虚拟机S->stringClass, "toZiFuChuan", 获取字符串自己的字符串);
   绑定方法到指定的类M(虚拟机S->stringClass, "count", 返回字符串的字节数);

   //List类
   虚拟机S->listClass = VALUE_TO_CLASS(获取核心类的值(coreModule, "List"));
   绑定方法到指定的类M(虚拟机S->listClass->objHeader.class, "new()", 创建一个新的list);
   绑定方法到指定的类M(虚拟机S->listClass, "[_]", 索引list元素);
   绑定方法到指定的类M(虚拟机S->listClass, "[_]=(_)", list只支持数字作为下标);
   绑定方法到指定的类M(虚拟机S->listClass, "add(_)", 直接追加到list中);
   绑定方法到指定的类M(虚拟机S->listClass, "addCore_(_)", 编译list直接量);
   绑定方法到指定的类M(虚拟机S->listClass, "clear()", 清空list);
   绑定方法到指定的类M(虚拟机S->listClass, "count", 返回list元素个数);
   绑定方法到指定的类M(虚拟机S->listClass, "insert(_,_)", list插入元素);
   绑定方法到指定的类M(虚拟机S->listClass, "iterate(_)", 迭代list);
   绑定方法到指定的类M(虚拟机S->listClass, "iteratorValue(_)", 返回list迭代值);
   绑定方法到指定的类M(虚拟机S->listClass, "removeAt(_)", 删除list中指定位置的元素);

   //map类
   虚拟机S->mapClass = VALUE_TO_CLASS(获取核心类的值(coreModule, "Map"));
   绑定方法到指定的类M(虚拟机S->mapClass->objHeader.class, "new()", 创建map对象);
   绑定方法到指定的类M(虚拟机S->mapClass, "[_]", 返回map键对应的值);
   绑定方法到指定的类M(虚拟机S->mapClass, "[_]=(_)", 设置map键setter);
   绑定方法到指定的类M(虚拟机S->mapClass, "addCore_(_,_)", 编译map字面量);
   绑定方法到指定的类M(虚拟机S->mapClass, "clear()", 清除map);
   绑定方法到指定的类M(虚拟机S->mapClass, "containsKey(_)", map是否包含键);
   绑定方法到指定的类M(虚拟机S->mapClass, "count", map中entry个数);
   绑定方法到指定的类M(虚拟机S->mapClass, "remove(_)", 删除map指定键对应值);
   绑定方法到指定的类M(虚拟机S->mapClass, "iterate_(_)", 迭代map中entry);
   绑定方法到指定的类M(虚拟机S->mapClass, "keyIteratorValue_(_)", map键迭代值);
   绑定方法到指定的类M(虚拟机S->mapClass, "valueIteratorValue_(_)", map值迭代值);

   //range类
   虚拟机S->rangeClass = VALUE_TO_CLASS(获取核心类的值(coreModule, "Range"));
   绑定方法到指定的类M(虚拟机S->rangeClass, "from", 返回范围的起始值);
   绑定方法到指定的类M(虚拟机S->rangeClass, "to", 返回范围的结束值);
   绑定方法到指定的类M(虚拟机S->rangeClass, "min", 返回范围起始和结束较小的值); 
   绑定方法到指定的类M(虚拟机S->rangeClass, "max", 返回范围起始和结束较大的值);
   绑定方法到指定的类M(虚拟机S->rangeClass, "iterate(_)", 迭代范围中的值);
   绑定方法到指定的类M(虚拟机S->rangeClass, "iteratorValue(_)", 直接返回迭代器);

   //system类
   Class* systemClass = VALUE_TO_CLASS(获取核心类的值(coreModule, "System"));
   绑定方法到指定的类M(systemClass->objHeader.class, "clock", 返回以秒为单位的系统时钟);
   绑定方法到指定的类M(systemClass->objHeader.class, "gc()", 启动系统垃圾回收器);
   绑定方法到指定的类M(systemClass->objHeader.class, "importModule(_)", 系统导入模块);
   绑定方法到指定的类M(systemClass->objHeader.class, "getModuleVariable(_,_)", 系统获取模块变量);
   绑定方法到指定的类M(systemClass->objHeader.class, "writeZiFuChuan_(_)", 系统输出字符串);

   //在核心自举过程中创建了很多ObjZiFuChuan对象,创建过程中需要调用initObjHeader初始化对象头,
   //使其class指向vm->stringClass.但那时的vm->stringClass尚未初始化,因此现在更正.
   对象头S* objHeader = 虚拟机S->所有已分配对象链表;
   while (objHeader != NULL) {
      if (objHeader->type == 对象类型_字符串) {
	 objHeader->class = 虚拟机S->stringClass;
      }
      objHeader = objHeader->next;
   }
}
